package cn.com.shopec.erp.system.service.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.hibernate.Hibernate;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.shopec.erp.common.constant.SZSCMConstant;
import cn.com.shopec.erp.common.page.PageFinder;
import cn.com.shopec.erp.common.page.PageQuery;
import cn.com.shopec.erp.common.utils.LogicUtil;
import cn.com.shopec.erp.common.utils.StringUtil;
import cn.com.shopec.erp.system.constant.SystemConstant;
import cn.com.shopec.erp.system.dao.IAccessDao;
import cn.com.shopec.erp.system.dao.IRoleDao;
import cn.com.shopec.erp.system.entity.Access;
import cn.com.shopec.erp.system.entity.Role;
import cn.com.shopec.erp.system.service.IRoleService;
import cn.com.shopec.erp.system.vo.RoleVo;
import cn.com.shopec.erp.system.vo.UserVo;

/**
 * 
 * @ClassName RoleServiceImpl
 * @Description 角色Service实现
 * @author chengui
 * @date 2013-5-30 上午11:02:56
 */
@Service
public class RoleServiceImpl implements IRoleService {
	
	@Resource private IRoleDao roleDao;
	@Resource private IAccessDao accessDao;

	@Override
	public PageFinder<RoleVo> getPagedRoleVos(RoleVo roleVo, PageQuery pageQuery)
			throws Exception {
		PageFinder<Role> pagedRoles = getPagedRoles(roleVo, pageQuery);
		PageFinder<RoleVo> pagedRoleVos = new PageFinder<RoleVo>(pagedRoles.getPageNo(), pagedRoles.getPageSize(), pagedRoles.getRowCount());
		List<RoleVo> roleVos = convertToRoleVos(pagedRoles.getData());
		pagedRoleVos.setData(roleVos);
		return pagedRoleVos;
	}
	
	/**
	 * 
	 * @MethodName convertToRoleVos
	 * @Description 将角色集合转换成角色Vo集合
	 * @author chengui
	 * @date 2013-5-30 下午5:05:17
	 * @param data
	 * @return List<RoleVo>
	 */
	private List<RoleVo> convertToRoleVos(List<Role> data) {
		List<RoleVo> roleVos = new ArrayList<RoleVo>();
		if (null != data && data.size() > 0) {
			RoleVo roleVo = null;
			for (Role role : data) {
				roleVo = new RoleVo();
				convertToUserVo(role, roleVo);
				roleVos.add(roleVo);
			}
		}
		return roleVos;
	}
	
	/**
	 * 
	 * @MethodName convertToUserVo
	 * @Description 将角色转换成角色Vo
	 * @author chengui
	 * @date 2013-5-30 下午5:06:23
	 * @param role
	 * @param roleVo
	 */
	private void convertToUserVo(Role role, RoleVo roleVo) {
		BeanUtils.copyProperties(role, roleVo);
	}

	/**
	 * 
	 * @MethodName getPagedRoles
	 * @Description 分页查询供应链角色
	 * @author chengui
	 * @date 2013-5-30 下午5:03:29
	 * @param roleVo
	 * @param pageQuery
	 * @return PageFinder<Role>
	 */
	private PageFinder<Role> getPagedRoles(RoleVo roleVo, PageQuery pageQuery) {
		DetachedCriteria criteria = roleDao.createCriteria();
		if (null != roleVo) {
			if (StringUtil.isExist(roleVo.getRoleName())) {
				criteria.add(Restrictions.like("roleName", roleVo.getRoleName(), MatchMode.ANYWHERE));
			}
		}
		criteria.add(Restrictions.eq("deleteFlag", SystemConstant.DELETE_FLAG_1));
		PageFinder<Role> pagedRoles = roleDao.pagedByCriteria(criteria, pageQuery.getPage(), pageQuery.getPageSize());
		return pagedRoles;
	}

	@Override
	public void addRole(RoleVo roleVo) throws Exception {
		Role role = new Role();
		role.setRoleName(roleVo.getRoleName());
		role.setRoleCode(roleVo.getRoleCode());
		role.setRoleType(roleVo.getRoleType());
		role.setRemark(roleVo.getRemark());
		roleDao.save(role);
	}

	@Override
	public String roleCodeExist(RoleVo roleVo) throws Exception {
		Role role = null;
		if (null != roleVo) {
			if (StringUtil.isExist(roleVo.getRoleCode())) {
				role = roleDao.findUniqueBy("roleCode", roleVo.getRoleCode());
			}
		}
		if (null != role) {
			return SystemConstant.ROLE_CODE_EXISTS_YES;
		} else {
			return SystemConstant.ROLE_CODE_EXISTS_NO;
		}
	}

	@Override
	public RoleVo getRoleVo(RoleVo roleVo) throws Exception {
		Role role = roleDao.getById(roleVo.getId());
		RoleVo rv = new RoleVo();
		convertToUserVo(role, rv);
		return rv;
	}
	
	@Transactional
	@Override
	public void modifyRole(RoleVo roleVo) throws Exception {
		Role role = roleDao.getById(roleVo.getId());
		role.setRoleName(roleVo.getRoleName());
		role.setRoleType(roleVo.getRoleType());
		role.setRemark(roleVo.getRemark());
		roleDao.update(role);
	}

	@Override
	public void deleteRole(RoleVo roleVo) throws Exception {
		Role role = roleDao.getById(roleVo.getId());
		role.setDeleteFlag(SystemConstant.DELETE_FLAG_0);
		roleDao.update(role);
	}

	@Override
	public List<RoleVo> getAllRoleVo() throws Exception {
		List<Role> roles = getAllRole();
		List<RoleVo> roleVos = convertToRoleVos(roles);
		return roleVos;
	}
	
	/**
	 * 
	 * @MethodName getAllRole
	 * @Description 获得所有角色
	 * @author chengui
	 * @date 2013-5-30 下午8:23:02
	 * @return
	 */
	private List<Role> getAllRole() {
		DetachedCriteria criteria = roleDao.createCriteria();
		criteria.add(Restrictions.eq("deleteFlag", SystemConstant.DELETE_FLAG_1));
		List<Role> roles = roleDao.findByCriteria(criteria);
		return roles;
	}

	@Override
	public List<Role> getRoles(UserVo userVo) throws Exception {
		DetachedCriteria criteria = roleDao.createCriteria();
		if (null != userVo) {
			criteria.add(Restrictions.in("id", null == userVo.getOwnRoleIds() ? new String[]{""} : userVo.getOwnRoleIds()));
		}
		criteria.add(Restrictions.eq("deleteFlag", SystemConstant.DELETE_FLAG_1));
		List<Role> roles = roleDao.findByCriteria(criteria);
		return roles;
	}
	
	@Override
	public List<Role> roleListByRoleCode(String roleCode) {
		DetachedCriteria detachedCriteria = roleDao.createCriteria();
		detachedCriteria.add(Restrictions.eq("deleteFlag", SZSCMConstant.DELETE_FLAG_NO));
		if(null!=roleCode && LogicUtil.isNotNullAndEmpty(roleCode)){
			detachedCriteria.add(Restrictions.eq("roleCode", roleCode));
		}
		return roleDao.findByCriteria(detachedCriteria);
	}
	
	@Transactional
	@Override
	public void allocateAccess(RoleVo roleVo) throws Exception {
		Role role = roleDao.getById(roleVo.getId());
		Set<Access> accesses = getAccesses(roleVo);
		role.setAccesses(accesses);
		roleDao.update(role);
	}
	
	/**
	 * 
	 * @MethodName getAccesses
	 * @Description 获得权限集合
	 * @author chengui
	 * @date 2013-6-1 下午5:56:42
	 * @param roleVo
	 * @return
	 */
	private Set<Access> getAccesses(RoleVo roleVo) throws Exception {
		Set<Access> sAccesses = new HashSet<Access>();
		
		String[] menuStructures = roleVo.getMenuStructures().split(",");
		DetachedCriteria criteria = accessDao.createCriteria();
		criteria.createAlias("menu", "menu");
		criteria.add(Restrictions.in("menu.structure", menuStructures));
		criteria.add(Restrictions.eq("deleteFlag", SystemConstant.DELETE_FLAG_1));
		List<Access> lAccesses = accessDao.findByCriteria(criteria);
		List<Access> allNeedAccesses = setNeedAccesses(lAccesses);
		sAccesses.addAll(allNeedAccesses);
		return sAccesses;
	}
	
	/**
	 * 
	 * @MethodName setChildrenAccesses
	 * @Description 设置子节点权限
	 * @author chengui
	 * @date 2013-6-1 下午6:07:43
	 * @param lAccesses
	 * @throws Exception
	 */
	private List<Access> setNeedAccesses(List<Access> lAccesses) throws Exception {
		List<Access> allNeedAccesses = new ArrayList<Access>();
		allNeedAccesses.addAll(lAccesses);
		if (null != lAccesses && lAccesses.size() > 0) {
			for (Access access : lAccesses) {
				setParentAccesses(access, allNeedAccesses);
			}
		}
		return allNeedAccesses;
	}
	
	/**
	 * 
	 * @MethodName setParentAccesses
	 * @Description 父节点添加权限
	 * @author chengui
	 * @date 2013-6-5 上午9:29:56
	 * @param access
	 * @param allNeedAccesses
	 */
	private void setParentAccesses(Access access, List<Access> allNeedAccesses) {
		Hibernate.initialize(access.getMenu());
		if (null != access.getMenu().getMenu()) {
			allNeedAccesses.add(access.getMenu().getMenu().getAccess());
			setParentAccesses(access.getMenu().getMenu().getAccess(), allNeedAccesses);
		}
	}

	@Override
	public List<RoleVo> getRoleVos(UserVo userVo) throws Exception {
		DetachedCriteria criteria = roleDao.createCriteria();
		if (null != userVo) {
			criteria.createAlias("users", "users");
			criteria.add(Restrictions.eq("users.id", userVo.getId()));
			criteria.add(Restrictions.eq("users.deleteFlag", SystemConstant.DELETE_FLAG_1));
		}
		criteria.add(Restrictions.eq("deleteFlag", SystemConstant.DELETE_FLAG_1));
		List<Role> roles = roleDao.findByCriteria(criteria);
		List<RoleVo> roleVos = convertToRoleVos(roles);
		return roleVos;
	}

	@Override
	public List<Role> roleList(String roleName) {
		DetachedCriteria detachedCriteria = roleDao.createCriteria();
		detachedCriteria.add(Restrictions.eq("deleteFlag", SZSCMConstant.DELETE_FLAG_NO));
		if(null!=roleName && LogicUtil.isNotNullAndEmpty(roleName)){
			detachedCriteria.add(Restrictions.eq("roleName", roleName));
		}
		return roleDao.findByCriteria(detachedCriteria);
	}

}
